﻿using System;
using System.Security;
using System.Security.Principal;
using System.Web;
using System.Web.Security;
using System.IO;
using DotNetNuke.Services.Log.EventLog;
using DotNetNuke.Services.FileSystem;
using DotNetNuke.Entities.Portals;
using System.Collections;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Common;
using System.Threading;
using DotNetNuke.Services.Scheduling;

namespace DotNetNuke.DotNetNuke.Common
{

    public class Initialize
    {
        // Fields
        private static bool InitializedAlready;
        private static object InitializeLock = new object();

        // Methods
        private static void CacheMappedDirectory()
        {
            FolderController objFolderController = new FolderController();
            ArrayList arrPortals = new PortalController().GetPortals();
            for (int i = 0; i <= arrPortals.Count; i++)
            {
                PortalInfo objPortalInfo = (PortalInfo)arrPortals[i];
                objFolderController.SetMappedDirectory(objPortalInfo, HttpContext.Current);
            }
        }

        private static string CheckVersion(HttpApplication app)
        {
            bool AutoUpgrade;
            bool UseWizard;
            HttpServerUtility Server = app.Server;
            if (Config.GetSetting("AutoUpgrade") == null)
            {
                AutoUpgrade = true;
            }
            else
            {
                AutoUpgrade = bool.Parse(Config.GetSetting("AutoUpgrade"));
            }
            if (Config.GetSetting("UseInstallWizard") == null)
            {
                UseWizard = true;
            }
            else
            {
                UseWizard = bool.Parse(Config.GetSetting("UseInstallWizard"));
            }
            string retValue = Null.NullString;
            switch (Globals.GetUpgradeStatus())
            {
                case Globals.UpgradeStatus.Upgrade:
                    if (!AutoUpgrade)
                    {
                        CreateUnderConstructionPage(Server);
                        return "~/Install/UnderConstruction.htm";
                    }
                    return "~/Install/Install.aspx?mode=upgrade";

                case Globals.UpgradeStatus.Install:
                    if (!AutoUpgrade)
                    {
                        CreateUnderConstructionPage(Server);
                        return "~/Install/UnderConstruction.htm";
                    }
                    if (!UseWizard)
                    {
                        return "~/Install/Install.aspx?mode=install";
                    }
                    return "~/Install/InstallWizard.aspx";

                case Globals.UpgradeStatus.None:
                    return retValue;

                case Globals.UpgradeStatus.Error:
                    CreateUnderConstructionPage(Server);
                    return "~/Install/UnderConstruction.htm";
            }
            return retValue;
        }

        private static void CreateUnderConstructionPage(HttpServerUtility server)
        {
            if (!File.Exists(server.MapPath("~/Install/UnderConstruction.htm")) && File.Exists(server.MapPath("~/Install/UnderConstruction.template.htm")))
            {
                File.Copy(server.MapPath("~/Install/UnderConstruction.template.htm"), server.MapPath("~/Install/UnderConstruction.htm"));
            }
        }

        public static void Init(HttpApplication app)
        {
            HttpResponse Response = app.Response;
            string redirect = Null.NullString;
            if (!InitializedAlready)
            {
                lock (InitializeLock)
                {
                    if (InitializedAlready)
                    {
                        return;
                    }
                    redirect = InitializeApp(app);
                    InitializedAlready = true;
                }
                if (!string.IsNullOrEmpty(redirect))
                {
                    Response.Redirect(redirect, true);
                }
            }
        }

        private static string InitializeApp(HttpApplication app)
        {
            HttpServerUtility Server = app.Server;
            HttpRequest Request = app.Request;
            string redirect = Null.NullString;
            if (HttpContext.Current.Request.ApplicationPath == "/")
            {
                if (Config.GetSetting("InstallationSubfolder") == "")
                {
                    Globals.ApplicationPath = "";
                }
                else
                {
                    Globals.ApplicationPath = Config.GetSetting("InstallationSubfolder") + "/";
                }
            }
            else
            {
                Globals.ApplicationPath = Request.ApplicationPath;
            }
            Globals.ApplicationMapPath = AppDomain.CurrentDomain.BaseDirectory.Substring(0, AppDomain.CurrentDomain.BaseDirectory.Length - 1);
            Globals.ApplicationMapPath = Globals.ApplicationMapPath.Replace("/", @"\");
            Globals.HostPath = Globals.ApplicationPath + "/Portals/_default/";
            Globals.HostMapPath = Server.MapPath(Globals.HostPath);
            if (!Request.Url.LocalPath.EndsWith("InstallWizard.aspx"))
            {
                redirect = CheckVersion(app);
                if (string.IsNullOrEmpty(redirect))
                {
                    CacheMappedDirectory();
                    StartScheduler();
                    LogStart();
                    EventQueueController.ProcessMessages("Application_Start");
                }
            }
            return redirect;
        }

        public static void LogEnd()
        {
            try
            {
                ApplicationShutdownReason shutdownReason = HostingEnvironment.ShutdownReason;
                string shutdownDetail = "";
                switch (((int)shutdownReason))
                {
                    case 1:
                        shutdownDetail = "The AppDomain shut down because of the hosting environment.";
                        break;

                    case 2:
                        shutdownDetail = "The AppDomain shut down because of a change to Global.asax.";
                        break;

                    case 3:
                        shutdownDetail = "The AppDomain shut down because of a change to the application level configuration.";
                        break;

                    case 4:
                        shutdownDetail = "The AppDomain shut down because of a call to UnloadAppDomain.";
                        break;

                    case 5:
                        shutdownDetail = "The AppDomain shut down because of a change in the code access security policy file.";
                        break;

                    case 6:
                        shutdownDetail = "The AppDomain shut down because of a change to the Bin folder or files contained in it.";
                        break;

                    case 7:
                        shutdownDetail = "The AppDomain shut down because of a change to the App_Browsers folder or files contained in it.";
                        break;

                    case 8:
                        shutdownDetail = "The AppDomain shut down because of a change to the App_Code folder or files contained in it.";
                        break;

                    case 9:
                        shutdownDetail = "The AppDomain shut down because of a change to the App_GlobalResources folder or files contained in it.";
                        break;

                    case 10:
                        shutdownDetail = "The AppDomain shut down because of the maximum allowed idle time limit.";
                        break;

                    case 11:
                        shutdownDetail = "The AppDomain shut down because of a change to the physical path for the application.";
                        break;

                    case 12:
                        shutdownDetail = "The AppDomain shut down because of a call to Close.";
                        break;

                    case 13:
                        shutdownDetail = "The AppDomain shut down because of an AppDomain initialization error.";
                        break;

                    case 14:
                        shutdownDetail = "The AppDomain shut down because of the maximum number of dynamic recompiles of resources limit.";
                        break;

                    default:
                        shutdownDetail = "No shutdown reason provided.";
                        break;
                }
                EventLogController objEv = new EventLogController();
                LogInfo objEventLogInfo = new LogInfo();
                objEventLogInfo.BypassBuffering = true;
                objEventLogInfo.LogTypeKey = EventLogController.EventLogType.APPLICATION_SHUTTING_DOWN.ToString();
                objEventLogInfo.AddProperty("Shutdown Details", shutdownDetail);
                objEv.AddLog(objEventLogInfo);
            }
            catch (Exception exc)
            {
                DotNetNuke.Services.Exceptions.Exceptions.LogException(exc);
            }
            LoggingProvider.Instance().PurgeLogBuffer();
        }

        public static void LogStart()
        {
            EventLogController objEv = new EventLogController();
            LogInfo objEventLogInfo = new LogInfo();
            objEventLogInfo.BypassBuffering = true;
            objEventLogInfo.LogTypeKey = EventLogController.EventLogType.APPLICATION_START.ToString();
            objEv.AddLog(objEventLogInfo);
        }

        public static void RunSchedule(HttpRequest request)
        {
            if (((request.Url.LocalPath.ToLower().EndsWith("install.aspx") || request.Url.LocalPath.ToLower().EndsWith("installwizard.aspx")) ? 1 : 0) == 0)
            {
                try
                {
                    if ((((SchedulingProvider.SchedulerMode == SchedulerMode.REQUEST_METHOD) && SchedulingProvider.ReadyForPoll) ? 1 : 0) != 0)
                    {
                        SchedulingProvider provider1 = SchedulingProvider.Instance();
                        Thread RequestScheduleThread = new Thread(new ThreadStart(provider1.ExecuteTasks));
                        RequestScheduleThread.IsBackground = true;
                        RequestScheduleThread.Start();
                        SchedulingProvider.ScheduleLastPolled = DateAndTime.Now;
                    }
                }
                catch (Exception exc)
                {
                    DotNetNuke.Services.Exceptions.Exceptions.LogException(exc);
                }
            }
        }

        public static void StartScheduler()
        {
            if (SchedulingProvider.SchedulerMode == SchedulerMode.TIMER_METHOD)
            {
                SchedulingProvider.Instance().RunEventSchedule(EventName.APPLICATION_START);
                SchedulingProvider provider1 = SchedulingProvider.Instance();
                Thread newThread = new Thread(new ThreadStart(provider1.Start));
                newThread.IsBackground = true;
                newThread.Start();
            }
        }

        public static void StopScheduler()
        {
            SchedulingProvider.Instance().Halt("Stopped by Application_End");
        }
    }




}
